package com.ksyun.campus.metaserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ksyun.campus.metaserver.domain.DataServerInfo;
import com.ksyun.campus.metaserver.domain.FileInfo;
import com.ksyun.campus.metaserver.domain.Result;
import com.ksyun.campus.metaserver.mapper.FileInfoMapper;
import com.ksyun.campus.metaserver.service.MetaService;
import com.ksyun.campus.metaserver.services.RegistService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MetaServiceImpl implements MetaService {

    private static final Logger log = LoggerFactory.getLogger(MetaServiceImpl.class);
    @Resource
    private RegistService registService;

    @Resource
    private FileInfoMapper fileInfoMapper;

    @Override
    public Result pickDataServer() {
        // 获取所有的DataServer
        List<DataServerInfo> dslist = registService.getDslist();
        System.out.println(dslist);

        if (dslist.size() < 3) {
            // 副本数量小于三个，返回错误信息
            log.error("副本数量小于三个");
            return Result.fail("副本数量小于三个");
        }

        if (dslist.size() == 3) {
            // 副本数量等于三个，不进行负载均衡，直接返回三个副本的信息

            return Result.success("只有三个DataServer，全部返回", dslist);
        }

        // 副本数量大于三个时，进行负载均衡
        dslist.forEach(ds -> {
            // 查询数据库，找到该DataServer上所有文件的大小，并加总
            List<FileInfo> filesOnServer = fileInfoMapper.selectList(new LambdaQueryWrapper<FileInfo>()
                    .eq(FileInfo::getCopyLocationOne, "dataServer" + ds.getIpAddress() +"-"+ ds.getPort())
                    .or(wrapper -> wrapper.eq(FileInfo::getCopyLocationTwo, "dataServer" + ds.getIpAddress() +"-"+ ds.getPort()))
                    .or(wrapper -> wrapper.eq(FileInfo::getCopyLocationThree, "dataServer" + ds.getIpAddress() +"-"+ ds.getPort()))
            );


            // 计算文件大小总和
            Long totalFileSize = filesOnServer.stream().mapToLong(FileInfo::getFileSize).sum();
            ds.setUseCapacity(totalFileSize.intValue());
        });



        // 根据已使用容量进行排序，并选择使用容量最小的三个DataServer
        List<DataServerInfo> selectedServers = dslist.stream()
                .sorted((ds1, ds2) -> Long.compare(ds1.getUseCapacity(), ds2.getUseCapacity()))
                .limit(3)
                .collect(Collectors.toList());

        // 返回选择的三个DataServer
        log.info("选取了最小使用容量的三个DataServer：{}", selectedServers);
        return Result.success("选取了最小使用容量的三个DataServer", selectedServers);
    }
}
